﻿using System;
using System.Collections.Generic;
using System.Text;
using Stauffware.Common.Core;
//using Stauffware.Common.Time;
using System.Globalization;
using NUnit.Framework;

using Stauffware.Common.Time.DateParsingUnderDevelopment;

namespace UnitTests.Time
{
	//#################################################################################
	/// <summary>
	/// Test parameters for one date lexer test.
	/// </summary>

	class TestParams
	{
		public readonly string Input;
		public readonly int MaxLexemes;
		public readonly int MaxNameLen;

		public readonly int ExpectedCharsLexed;
		public readonly IList<Lexeme> ExpectedLexemes;

		//-----------------------------------------------------------------------------
		// produce nice display in NUnit GUI

		public override string ToString ( )
		{
			if (this._toStringCache == null)
			{
				this._toStringCache = "";
				foreach (Lexeme lx in this.ExpectedLexemes)
					this._toStringCache += "," + lx.ToString();
				if (this._toStringCache != "")
					this._toStringCache = this._toStringCache.Substring(1);
				this._toStringCache = "\"" + this.Input + "\", " + this.MaxLexemes.ToString() + ", " + 
								this.MaxNameLen.ToString() + "; expect " + 
								this.ExpectedCharsLexed.ToString() + ", {" + this._toStringCache + "}";
			}
			return this._toStringCache;
		}
		private string _toStringCache;

		//-----------------------------------------------------------------------------

		private TestParams (string input, int maxLexemes, int maxNameLen,
									int expectedCharsLexed, IList<Lexeme> expectedLexemes)
		{
			this.Input = input;
			this.MaxLexemes = maxLexemes;
			this.MaxNameLen = maxNameLen;
			this.ExpectedCharsLexed = (expectedCharsLexed == -1) ? input.Length : expectedCharsLexed;
			this.ExpectedLexemes = expectedLexemes;
		}

		public TestParams ( ) { }

		//-----------------------------------------------------------------------------

		public void Run ( )
		{
			Lexer lexer = new Lexer(this.Input, this.MaxLexemes, this.MaxNameLen);

			int n = 0;

			for (; ; )
			{
				System.Console.WriteLine("[" + n.ToString() + "] " + this.ExpectedLexemes[n].ToString() + 
											"   " + lexer.CurrentLexeme.ToString());
				NUnit.Framework.Assert.AreEqual(this.ExpectedLexemes[n], lexer.CurrentLexeme, "lexeme " + n.ToString());
				if (lexer.CurrentLexeme.Type == LexemeType.EndOfInput)
					break;
				n++;
				lexer.Next();
			}

			NUnit.Framework.Assert.AreEqual(this.ExpectedCharsLexed, lexer.CharsLexed);
		}

		//-----------------------------------------------------------------------------

		public static IEnumerable<TestParams> CreateTests ( )
		{
			List<TestParams> tests = new List<TestParams>();

			tests.Add(new TestParams(
						"23 Jan 1987", 10, 20, -1, new Lexeme[]
						{ 
							new Lexeme(LexemeType.StartOfInput),
							new Lexeme(LexemeType.Number, "23", 23),
							new Lexeme(LexemeType.Spaces, " "),
							new Lexeme(LexemeType.Name, "Jan"),
							new Lexeme(LexemeType.Spaces, " "),
							new Lexeme(LexemeType.Number, "1987", 1987),
							new Lexeme(LexemeType.EndOfInput),
						}));

			tests.Add(new TestParams(
						"", 10, 20, 0, new Lexeme[]
						{ 
							new Lexeme(LexemeType.StartOfInput),
							new Lexeme(LexemeType.EndOfInput),
						}));

			//tests.Add(new TestParams(
			//            "   ", 10, 20, -1, new Lexeme[]
			//            { 
			//                new Lexeme(LexemeType.StartOfInput),
			//                new Lexeme(LexemeType.Spaces, "   "),
			//                new Lexeme(LexemeType.EndOfInput),
			//            }));

			tests.Add(new TestParams(
						"1987-06-25 ?!?", 10, 20, 11, new Lexeme[]
						{ 
							new Lexeme(LexemeType.StartOfInput),
							new Lexeme(LexemeType.Number, "1987", 1987),
							new Lexeme(LexemeType.Separator, "-"),
							new Lexeme(LexemeType.Number, "06", 6),
							new Lexeme(LexemeType.Separator, "-"),
							new Lexeme(LexemeType.Number, "25", 25),
							new Lexeme(LexemeType.Spaces, " "),
							new Lexeme(LexemeType.EndOfInput),
						}));

			return tests;
		}

		//-----------------------------------------------------------------------------
	}

	//#################################################################################

	class TestThingy
	{
		//-----------------------------------------------------------------------------

		[Test, TestCaseSource(typeof(TestParams), "CreateTests")]
		public void RunTest (TestParams tp)
		{
			tp.Run();
		}


	}

	//#################################################################################
}
